/* Gyroe 1.0.0 */
/* error.c : Handle warning adds, and warning output. 
   Also handles error output for all front-end files.*/

#include "euphoria.h"
#include "main-.h"

int _6screen_output(int f, int msg)
{
    EPuts(f, msg);
    DeRefDS(msg);
}

int _6Warning(int msg)
{
    int p = 0;
    int _598 = 0;
    int _1, _2;

    if (_4OpWarning) {
        /* Reset error_stack, or we might duplicate the message. */
        RefDS(_39);
        error_stack = _39;

        /* Warning: %s\n */
        err_add(NewString("Warning : "));
        err_add(msg);
        err_add(NewString("\n"));

        p = error_stack;

        RefDS(_39);
        error_stack = _39;

        /* Is this a duplicate? */
        if (find(p, _6warning_list)) {
            /* Yes. Don't add it to the warning list. */
            return 0;
        }
        // warning_list = append(warning_list, p)
        RefDS(p);
        Append(&_6warning_list, _6warning_list, p);
    /* Else user doesn't want warnings. */
    }
}

int _6ShowWarnings(int errfile)
{
    int cache, i;

    object_ptr Base;
    s1_ptr ptr;

    ptr = SEQ_PTR(_6warning_list);
    Base = ptr->base;

    for (i = 1; i < ptr->length;i++) {
        if (errfile == 0) {
            // screen_output(STDERR, warning_list[i])
            cache = Base[i];
            RefDS(cache);
            _6screen_output(2, cache);

            if ((i % 20) == 0) {
                EPuts(2, _607); /* \nPress Enter to continue, q to quit\n\n */

                if (getc(xstdin) == 113) /* 'q' */
                    break;
            }
        }
        else {
            // puts(errfile, warning_list[i])
            cache = Base[i];
            RefDS(cache);
            EPuts(errfile, cache);
        }
    }
}

int _6Cleanup(int status)
{

    _6ShowWarnings(0);
    _6screen_output(2, NewString("\nPress Enter\n"));

    if (getc(xstdin) == 0) {}

    UserCleanup(status);
}

int _6OpenErrFile()
{
    _6TempErrFile = EOpen(_6TempErrName, _621);

    if (_6TempErrFile == -1) {
        /* Can't make a error file... */
        RefDS(_626);
        _6screen_output(2, _626); /* Can't create error message file: */

        RefDS(_6TempErrName);
        _6screen_output(2, _6TempErrName);

        RefDS(_627);
        _6screen_output(2, _627); /* \n */
    }

    UserCleanup(1);
}

int _6ShowErr(int f)
{
    int _628, _634;
    int _1, _2;
    int i = 1;

    object_ptr Base;
    s1_ptr ptr;

    if (SEQ_PTR(_4file_name)->length == 0)
        return 0;

    ptr = SEQ_PTR(_6ThisLine);
    Base = ptr->base;

    if (Base[1] == 26) { /* End of file character */
        RefDS(_632);
        _6screen_output(f, _632); /* <end-of-file> */
    }
    else {
        Ref(_6ThisLine);
        _6screen_output(f, _6ThisLine);
    }

    // for i = 1 to bp-2 do -- bp-1 points to last character read
    for (i = 1;i <= _6bp-2;i++) {
        /* Use spaces unless user used tab on this line. Otherwise,
           the '^' will point to the wrong spot. */
        if (Base[i] == 9) { /* '\t' */
            RefDS(_636);
            _6screen_output(f, _636); /* '\t' */
        }
        else {
            RefDS(_637);
            _6screen_output(f, _637); /* ' ' */
        }
    }

    //     screen_output(f, "^\n\n")
    RefDS(_638);
    _6screen_output(f, _638);

    DeRef(_628);
}

int _6CompileErr(int msg)
{
    int errmsg = 0;
    int _639;
    int _1, _2;

    if (SEQ_PTR(_4file_name)->length) {
        /* %.99s:%d\n%s\n */
        object_ptr Base;
        s1_ptr ptr;

        ptr = SEQ_PTR(_4file_name);
        Base = ptr->base;

        /* If set_error_stack called us, msg would contain it. */
        err_add(Base[_4current_file_no]);
        err_add(NewString(":"));
        err_add(s1_from_int(_4line_number));
        err_add(msg);
        errmsg = error_stack;
    }
    else {
        RefDS(msg);
        DeRef(errmsg);
        errmsg = msg;
    }

    RefDS(errmsg);
    _6screen_output(2, errmsg);
    _6ShowErr(2); // STDERR
    /* First, print to STDERR. */

    _6OpenErrFile();
    /* Open the error file. */

    EPuts(_6TempErrFile, errmsg);
    _6ShowErr(_6TempErrFile);
    /* Place a copy in the error file. */

    _6ShowWarnings(_6TempErrFile);

    EPuts(_6TempErrFile, _627);
    EClose(_6TempErrFile);
    /* Make an extra line, then close. */

    DeRefDS(msg);
    DeRef(errmsg);
    DeRef(_639);
    /* Deref our vars, since we won't be coming back. */

    _6Cleanup(1);
}

int _6InternalErr(int msg)
{
    int _650;
    int _1, _2;
    object_ptr Base;
    s1_ptr ptr;

    /* Internal Error at %s:%d - %s\n */
    ptr = SEQ_PTR(_4file_name);
    Base = ptr->base;

    err_add(NewString("Internal Error at "));
    err_add(Base[_4current_file_no]);
    err_add(NewString(":"));
    err_add(s1_from_int(_4line_number));
    err_add(NewString(" - "));
    err_add(msg);
    err_add(NewString("\n\nPress Enter\n"));

    _6screen_output(2, error_stack);

    if (getc(xstdin)) {}

    DeRef(_650);
    RTFatal("divide by 0");
    StdPrint(1, _650, 1);

    DeRefDSi(msg);
    DeRef(_650);
}

object error_stack;
/* Place to store errors. */

void ebegin ()
/* Set error_stack to an empty s1, so we can append to it later. */
{
    RefDS(_39);
    error_stack = _39;
}

void err_add (s1_ptr s1)
/* Add to the error_stack from an s1. */
{
    Concat((object_ptr)&error_stack, error_stack, s1);
}

s1_ptr s1_from_int (int a)
/* Returns an s1 from an int. */
{
    return EPrintf(-9999999, NewString("%d"), a);
}

void set_err_stack ()
/* Sets up the error stack to go through CompileErr. 
   In the future, this should call code in CompileErr since it will be
   the standard error reporter. */
{
    /* FOR NOW. */
    /* TODO : Make this do what CompileErr does, instead of using CompileErr. */
    _6CompileErr(error_stack);
}

